from mongoengine import Document, StringField, DateTimeField, FloatField, IntField, ListField, URLField,ReferenceField,ObjectIdField,DictField
from bson import ObjectId
from datetime import datetime, timedelta

class User(Document):
    # 假设 openid 是唯一的 reg_type 0 小程序 1华为os
    openid = StringField(unique=True)
    nickname = StringField(required=True, max_length=50)
    # avatar = StringField()
    mobile = StringField(max_length=20)
    level = IntField(min_value=1)
    score = IntField(default=0)
    reg_type = IntField(default=0)
    password = StringField()
    created_at = DateTimeField(default=datetime.now)
    updated_at = DateTimeField(default=datetime.now)
    
    
    def save(self, *args, **kwargs):
        if not self.updated_at:  # 如果 updated_at 没有设置，则设置为创建时间
            self.updated_at = datetime.now()
        else:  # 否则更新为当前时间
            self.updated_at = datetime.now()
        super(User, self).save(*args, **kwargs)
        
    # 可以添加方法来表示业务逻辑，例如获取用户信息
    def get_user_info(self):
        return {
            "openid": self.openid,
            "nickname": self.nickname,
            # "avatar": self.avatar,
            "level": self.level,
            "score": self.score,
            "mobile": self.mobile,
            "reg_type": self.reg_type,
            # "password": self.password,
            "created_at": self.created_at.isoformat(),
            "updated_at": self.updated_at.isoformat(),
        }
        
class Books(Document):
    ysbookId = IntField(default=0)
    status = IntField(default=0)
    tags = ListField(StringField(), default=[])
    score = FloatField(null=True)
    scorerCount = IntField(default=0)
    title = StringField(null=True)
    author = StringField(null=True)
    intro = StringField(null=True)
    link = StringField(null=True)
    cover = StringField(null=True)
    countWord = IntField(null=True)
    updateAt = DateTimeField(null=True)
    caseId = IntField(default=0)
    lastUpdated = DateTimeField(default=lambda: datetime.now())  # 使用本地时间作为默认值
    
    
    # 可以添加方法来表示业务逻辑，例如获取用户信息
    def get_book_info(self):
        return {
            "id": str(self.id),
            "ysbookId": self.ysbookId,
            "status": self.status,
            "tags": self.tags,
            "score": self.score,
            "scorerCount": self.scorerCount,
            "title": self.title,
            "author": self.author,
            "cover": self.cover,
            "countWord": self.countWord,
            "updateAt": self.updateAt.strftime("%Y-%m-%d") if self.updateAt is not None else "",
            "intro": self.intro,
            "link": self.link,
            "caseId": self.caseId
        }
        
    def to_dict(self):
        # Convert MongoEngine document to a dict that can be serialized to JSON
        result = {}
        for field, value in self.to_mongo().items():
            if isinstance(value, ObjectId):
                result[field] = str(value)
            elif isinstance(value, list):
                result[field] = [str(item) if isinstance(item, ObjectId) else item for item in value]
            else:
                result[field] = value
        return result
 
class Comments(Document):
    book_id = ReferenceField('Books', reverse_delete_rule=0)  # 2 means CASCADE
    ysbookId = IntField(default=0)
    user_id = ObjectIdField()
    username = StringField(required=True)
    content = StringField(required=True)
    createdAt = DateTimeField(default=datetime.now)
    rating = FloatField(default=0)
    upvotes = IntField(default=0)
    ismiao = IntField(default=0)
    updated_at = DateTimeField(default=datetime.now)
    display = IntField(default=1)  # 是否显示
    
    def save(self, *args, **kwargs):
        if not self.updated_at:  # 如果 updated_at 没有设置，则设置为创建时间
            self.updated_at = datetime.now()
        else:  # 否则更新为当前时间
            self.updated_at = datetime.now()
        super(Comments, self).save(*args, **kwargs)

# 书单
class Nlist(Document):

    name = StringField(required=True, max_length=100)
    description = StringField(max_length=500)
    nickname = StringField(max_length=20)
    books = DictField()
    book_tags = ListField(StringField(), default=[])
    created_at = DateTimeField(default=datetime.now)
    updated_at = DateTimeField(default=datetime.now)
    created_by = ReferenceField('User')  # User 文档的引用
    like_count = IntField(default=0)  # 默认点赞数为0
    display = IntField(default=1)  # 是否显示
    # 保存时更新时间
    # def save(self, *args, **kwargs):
    #     if not self.updated_at:  # 如果 updated_at 没有设置，则设置为创建时间
    #         self.updated_at = datetime.now()
    #     # else:  # 否则更新为当前时间
    #         # self.updated_at = datetime.now()
    #     super(Nlist, self).save(*args, **kwargs)
    # 保存时更新时间，备份原始的 save 方法
    def save_original(self, *args, **kwargs):
        super(Nlist, self).save(*args, **kwargs)
    # 获取书单的基本信息
    def get_nlist_info(self):
        return {
            "id": str(self.id),
            "name": self.name,
            "description": self.description,
            "nickname": self.nickname,
            "book_ids": list(self.books.keys()),  # 从 books 字段中获取书籍 ID 列表
            "book_tags": self.book_tags,
            "created_at": self.created_at.isoformat(),
            "updated_at": self.updated_at.isoformat(),
            "created_by": str(self.created_by),  # 创建用户的 ID
            "like_count": self.like_count  # 返回点赞数
        }
    # 增加点赞数
    def increment_like(self):
        self.like_count += 1
        self.save_original()

    # 减少点赞数
    def decrement_like(self):
        if self.like_count > 0:
            self.like_count -= 1
            self.save_original()
            
# 书单点赞记录            
class UserLikeStats(Document):
    user_id = ObjectIdField(required=True)
    liked_nlists = DictField()

    def add_nlist_like(self, nlist_id):
        nlist_id_str = str(nlist_id)  # 将ObjectId类型转换为字符串类型
        if nlist_id_str not in self.liked_nlists:
            self.liked_nlists[nlist_id_str] = True
        self.save()

    def remove_nlist_like(self, nlist_id):
        nlist_id_str = str(nlist_id)  # 将ObjectId类型转换为字符串类型
        if nlist_id_str in self.liked_nlists:
            del self.liked_nlists[nlist_id_str]
        self.save()
# 龙空书单
class LkBookList(Document):
    """龙空书单数据模型"""
    listId = StringField(required=True, unique=True)  # 龙空书单ID (字符串格式)
    title = StringField(required=True, max_length=200)  # 书单标题
    description = StringField()  # 书单描述
    category = StringField(max_length=50)  # 分类 (male/female 等)
    bookCount = IntField(default=0)  # 书籍数量
    viewCount = IntField(default=0)  # 查看数
    favoritedCount = IntField(default=0)  # 收藏数
    
    # 作者信息
    author_uid = IntField()  # 作者UID
    author_name = StringField(max_length=100)  # 作者名称
    author_avatar = StringField()  # 作者头像 (null 时为空)
    
    avatars = ListField(StringField())  # 书单封面数组 (最多3张)
    isFavorited = IntField(default=0)  # 是否被当前用户收藏 (0/1, null视0)
    
    createdAt = DateTimeField()  # 创建时间
    lastActiveAt = DateTimeField()  # 最后活跃时间
    lastUpdated = DateTimeField(default=lambda: datetime.now())  # 本地最后更新时间
    booksLastSyncAt = DateTimeField()  # 书单书籍最后同步时间
    
    meta = {
        'indexes': [
            'listId',  # 书单ID索引
            'category',  # 分类索引
            '-viewCount',  # 浏览量倒序索引
            '-favoritedCount',  # 收藏量倒序索引
            '-lastActiveAt'  # 活跃时间倒序索引
        ]
    }
    
    def get_lklist_info(self):
        """获取书单详细信息"""
        return {
            "id": str(self.id),
            "listId": self.listId,
            "title": self.title,
            "description": self.description,
            "category": self.category,
            "bookCount": self.bookCount,
            "viewCount": self.viewCount,
            "favoritedCount": self.favoritedCount,
            "author": {
                "uid": self.author_uid,
                "name": self.author_name,
                "avatar": self.author_avatar
            },
            "avatars": self.avatars if self.avatars else [],
            "isFavorited": self.isFavorited,
            "createdAt": self.createdAt.isoformat() if self.createdAt else None,
            "lastActiveAt": self.lastActiveAt.isoformat() if self.lastActiveAt else None,
            "lastUpdated": self.lastUpdated.isoformat() if self.lastUpdated else None
        }

# 龙空书单中的书籍
class LkBookListBook(Document):
    """龙空书单中的书籍数据模型"""
    listId = StringField(required=True, db_field='listId')  # 所属书单ID
    rid = IntField(required=True)  # 评论ID
    bid = IntField(required=True)  # 书籍ID
    
    # 评分信息
    score = FloatField(default=0)  # 评分 (1-5)
    myRate = FloatField(default=0)  # 我的评分
    
    # 评论内容
    content_text = StringField()  # 评论文本内容(从 JSON 解析后的)
    dateline = DateTimeField()  # 评论创建时间
    lastpost = DateTimeField()  # 最后更新时间
    replies = IntField(default=0)  # 回复数
    likes = IntField(default=0)  # 点赞数
    
    # 书单信息
    addedAt = DateTimeField()  # 添加到书单的时间
    
    # 书籍信息
    book_title = StringField()  # 书名
    book_author = StringField()  # 作者
    book_cover = StringField()  # 封面
    book_wordCount = IntField(default=0)  # 字数
    book_finished = IntField(default=0)  # 是否完结 (0/1)
    book_tags = ListField(StringField())  # 标签
    book_intro = StringField()  # 书籍简介
    
    # 书籍统计
    book_score = FloatField(default=0)  # 书籍评分
    book_rateCount = IntField(default=0)  # 评分人数
    book_commentCount = IntField(default=0)  # 评论数
    book_addListCount = IntField(default=0)  # 添加到书单数
    
    lastUpdated = DateTimeField(default=lambda: datetime.now())  # 本地最后更新时间
    
    meta = {
        'indexes': [
            'listId',  # 书单ID索引
            'bid',  # 书籍ID索引
            ('listId', 'bid'),  # 组合索引
            '-addedAt',  # 添加时间倒序索引
            '-score'  # 评分倒序索引
        ]
    }
    
    def get_book_info(self):
        """获取书籍详细信息"""
        return {
            "id": str(self.id),
            "listId": self.listId,
            "rid": self.rid,
            "bid": self.bid,
            "score": self.score,
            "myRate": self.myRate,
            "content_text": self.content_text,
            "dateline": self.dateline.isoformat() if self.dateline else None,
            "lastpost": self.lastpost.isoformat() if self.lastpost else None,
            "replies": self.replies,
            "likes": self.likes,
            "addedAt": self.addedAt.isoformat() if self.addedAt else None,
            "book": {
                "bid": self.bid,
                "title": self.book_title,
                "author": self.book_author,
                "cover": self.book_cover,
                "wordCount": self.book_wordCount,
                "finished": self.book_finished,
                "tags": self.book_tags if self.book_tags else [],
                "intro": self.book_intro,
                "score": self.book_score,
                "rateCount": self.book_rateCount,
                "commentCount": self.book_commentCount,
                "addListCount": self.book_addListCount
            }
        }

# 书架
class Collect(Document):
    user = ReferenceField(User, reverse_delete_rule=0)
    book = ReferenceField(Books, reverse_delete_rule=0)
    added_at = DateTimeField(default=datetime.now)  # 记录添加时间

    def get_shujia_info(self):
        return {
            "user": str(self.user.id),
            "book": str(self.book.id),
            "book_title": self.book.title,           # 获取书名
            "cover": self.book.cover,    # 获取封面图
            "author": self.book.author,               # 获取作者
            "added_at": self.added_at.strftime("%Y-%m-%d")  # 只返回到天
        }
        
    @classmethod
    def get_all_books_for_user(cls, user):
        shujia_records = cls.objects(user=user)
        return [record.get_shujia_info() for record in shujia_records]    
        
# 建议表            
class Suggestion(Document):
    user_id = ObjectIdField(required=True)
    content = StringField(max_length=500)
    added_at = DateTimeField(default=datetime.now)  # 记录添加时间
    
    
# 配置表
class Config(Document):
    site_name = StringField()
    description = StringField()
    logo_url = StringField()
    tags = StringField()
    # 添加其他你需要的配置字段

# 公告表
class Notice(Document):
    title = StringField(required=True)
    content = StringField(required=True)
    createdAt = DateTimeField(auto_now_add=True)

class BookMonthlyTicket(Document):
    title = StringField(required=True)
    author = StringField(required=True)
    monthly_ticket = StringField(default="0")
    expire_at = DateTimeField(default=lambda: datetime.now() + timedelta(days=15))
    created_at = DateTimeField(default=datetime.now)

    def get_ticket_info(self):
        return {
            "title": self.title,
            "author": self.author,
            "monthly_ticket": self.monthly_ticket,
            "expire_at": self.expire_at.isoformat(),
            "created_at": self.created_at.isoformat()
        }

    @classmethod
    def get_monthly_ticket(cls, title, author):
        # 查询数据库中的月票数量
        book_ticket = cls.objects(title=title, author=author).first()
        
        if book_ticket:
            # 检查是否过期
            if datetime.now() < book_ticket.expire_at:
                return book_ticket.monthly_ticket
            else:
                # 过期后删除记录
                book_ticket.delete()
                return None
        return None

    @classmethod
    def set_monthly_ticket(cls, title, author, monthly_ticket):
        # 更新或创建记录
        cls.objects(title=title, author=author).update_one(
            upsert=True,
            title=title,
            author=author,
            monthly_ticket=monthly_ticket,
            expire_at=datetime.now() + timedelta(days=15)
        )